Support update --precise for registry deps
authorAlex Crichton <alex@alexcrichton.com>
Wed, 4 Feb 2015 00:55:07 +0000 (16:55 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 4 Feb 2015 00:55:07 +0000 (16:55 -0800)
Closes #1105

src/cargo/ops/cargo_generate_lockfile.rs
src/cargo/sources/registry.rs
tests/test_cargo_registry.rs

index 91de743272cb1d03614819e97e9d8be45051aacd..6b3f64d3daf951f5ed358b1ceb1b19aa56598cc6 100644 (file)
@@ -60,8 +60,16 @@ pub fn update_lockfile(manifest_path: &Path,
                 to_avoid.insert(dep);
                 match opts.precise {
                     Some(precise) => {
+                        // TODO: see comment in `resolve.rs` as well, but this
+                        //       seems like a pretty hokey reason to single out
+                        //       the registry as well.
+                        let precise = if dep.get_source_id().is_registry() {
+                            format!("{}={}", dep.get_name(), precise)
+                        } else {
+                            precise.to_string()
+                        };
                         let precise = dep.get_source_id().clone()
-                                         .with_precise(Some(precise.to_string()));
+                                         .with_precise(Some(precise));
                         try!(registry.add_sources(&[precise]));
                     }
                     None => {}
index d3e311cf135e270d9b628652113ec08104ae1fcd..922519547ab6bd477a558fadce04be1950c98ce9 100644 (file)
@@ -163,10 +163,10 @@ use std::io::fs::PathExtensions;
 use std::collections::HashMap;
 
 use curl::http;
-use git2;
 use flate2::reader::GzDecoder;
-use rustc_serialize::json;
+use git2;
 use rustc_serialize::hex::ToHex;
+use rustc_serialize::json;
 use tar::Archive;
 use url::Url;
 
@@ -477,10 +477,26 @@ impl<'a, 'b> Registry for RegistrySource<'a, 'b> {
             }
         }
 
-        let summaries = try!(self.summaries(dep.get_name()));
-        let mut summaries = summaries.iter().filter(|&&(_, yanked)| {
-            dep.get_source_id().get_precise().is_some() || !yanked
-        }).map(|&(ref s, _)| s.clone()).collect::<Vec<_>>();
+        let mut summaries = {
+            let summaries = try!(self.summaries(dep.get_name()));
+            summaries.iter().filter(|&&(_, yanked)| {
+                dep.get_source_id().get_precise().is_some() || !yanked
+            }).map(|s| s.0.clone()).collect::<Vec<_>>()
+        };
+
+        // Handle `cargo update --precise` here. If specified, our own source
+        // will have a precise version listed of the form `<pkg>=<req>` where
+        // `<pkg>` is the name of a crate on this source and `<req>` is the
+        // version requested (agument to `--precise`).
+        summaries.retain(|s| {
+            match self.source_id.get_precise() {
+                Some(p) if p.starts_with(dep.get_name()) => {
+                    let vers = &p[dep.get_name().len() + 1..];
+                    s.get_version().to_string() == vers
+                }
+                _ => true,
+            }
+        });
         summaries.query(dep)
     }
 }
@@ -491,8 +507,10 @@ impl<'a, 'b> Source for RegistrySource<'a, 'b> {
         // to look for, so we always atempt to perform an update here.
         //
         // If we have a precise version, then we'll update lazily during the
-        // querying phase.
-        if self.source_id.get_precise().is_none() {
+        // querying phase. Note that precise in this case is only
+        // `Some("locked")` as other `Some` values indicate a `cargo update
+        // --precise` request
+        if self.source_id.get_precise() != Some("locked") {
             try!(self.do_update());
         }
         Ok(())
index 2873d2ee3af5af36a98dd1ac3762d34ec942401b..3d1296c3bfdfa1be9de4f4fd74ddcbea135b6084 100644 (file)
@@ -462,23 +462,43 @@ test!(update_lockfile {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
+    println!("0.0.1");
     r::mock_pkg("bar", "0.0.1", &[]);
     assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
                 execs().with_status(0));
 
     r::mock_pkg("bar", "0.0.2", &[]);
+    r::mock_pkg("bar", "0.0.3", &[]);
     fs::rmdir_recursive(&paths::home().join(".cargo/registry")).unwrap();
+    println!("0.0.2 update");
     assert_that(p.process(cargo_dir().join("cargo")).arg("update")
-                 .arg("-p").arg("bar"),
+                 .arg("-p").arg("bar").arg("--precise").arg("0.0.2"),
                 execs().with_status(0).with_stdout(format!("\
 {updating} registry `[..]`
 ", updating = UPDATING).as_slice()));
 
+    println!("0.0.2 build");
     assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
                 execs().with_status(0).with_stdout(format!("\
 {downloading} [..] v0.0.2 (registry file://[..])
 {compiling} bar v0.0.2 (registry file://[..])
 {compiling} foo v0.0.1 ({dir})
+", downloading = DOWNLOADING, compiling = COMPILING,
+   dir = p.url()).as_slice()));
+
+    println!("0.0.3 update");
+    assert_that(p.process(cargo_dir().join("cargo")).arg("update")
+                 .arg("-p").arg("bar"),
+                execs().with_status(0).with_stdout(format!("\
+{updating} registry `[..]`
+", updating = UPDATING).as_slice()));
+
+    println!("0.0.3 build");
+    assert_that(p.process(cargo_dir().join("cargo")).arg("build"),
+                execs().with_status(0).with_stdout(format!("\
+{downloading} [..] v0.0.3 (registry file://[..])
+{compiling} bar v0.0.3 (registry file://[..])
+{compiling} foo v0.0.1 ({dir})
 ", downloading = DOWNLOADING, compiling = COMPILING,
    dir = p.url()).as_slice()));
 });